﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.IO;

namespace BesAsm.Stormwater.TimeSeries
{
  public static class TimeSeriesExtensions
  {
    public static TimeSeries<float> Resample(this TimeSeries<float> ts, TimeSpan interval, DateTime resampleStart, DateTime resampleEnd, ResampleType resampleType)
    {
      TimeSeries<float> newTs = new TimeSeries<float>();

      switch (resampleType)
      {
        case ResampleType.Average:
          return ts.ResampleAndAverage(interval, resampleStart, resampleEnd);
        case ResampleType.Max:
          throw new NotImplementedException();
        case ResampleType.Min:
          throw new NotImplementedException();
        case ResampleType.Total:
          return ts.ResampleAndTotal(interval, resampleStart, resampleEnd);
        default:
          throw new NotImplementedException();
      }

      return newTs;
    }

    private static TimeSeries<float> ResampleAndAverage(
      this TimeSeries<float> ts, TimeSpan interval, DateTime resampleStart, DateTime resampleEnd)
    {
      TimeSeries<float> newTs = new TimeSeries<float>();
      List<DateTime> newDates = new List<DateTime>();

      for (DateTime dt = resampleStart; dt <= resampleEnd; dt += interval)
        newDates.Add(dt);

      foreach (DateTime dt in newDates)
      {
        IEnumerable<KeyValuePair<DateTime, float>> neighbors = ts.Where(p => p.Key >= dt && p.Key < dt + interval);

        if (neighbors.Count() == 0) continue;

        int i = 0;
        float f = 0;
        foreach (KeyValuePair<DateTime, float> kvp in neighbors)
        {
          f += kvp.Value;
          i++;
        }
        f /= i;
        newTs.Add(dt, f);
      }

      return newTs;
    }

    private static TimeSeries<float> ResampleAndTotal(
      this TimeSeries<float> ts, TimeSpan interval, DateTime resampleStart, DateTime resampleEnd)
    {
      TimeSeries<float> newTs = new TimeSeries<float>();
      List<DateTime> newDates = new List<DateTime>();
      TimeSpan oldInterval = ts.Interval.Value;

      for (DateTime dt = resampleStart; dt <= resampleEnd; dt += interval)
        newDates.Add(dt);

      foreach (DateTime dt in newDates)
      {
        TimeSeries<float> neighbors = new TimeSeries<float>();

        for (DateTime dt2 = dt; dt2 < dt + interval; dt2 += oldInterval)
        {
          neighbors.Add(dt2, ts[dt2]);          
        }
        
        if (neighbors.Count() == 0) continue;

        int i = 0;
        float f = 0;
        foreach (KeyValuePair<DateTime, float> kvp in neighbors)
        {
          f += kvp.Value;        
        }
        
        newTs.Add(dt, f);
      }

      return newTs;
    }

    public static void WriteTimeSeries<T>(this TimeSeries<T> ts, string file)
    {
      StreamWriter writer = null;
      try
      {
        writer = new StreamWriter(file);

        foreach (KeyValuePair<DateTime, T> kvp in ts)
        {
          writer.Write("{0},", kvp.Key.ToString("MM/dd/yyyy HH:mm:ss"));
          writer.WriteLine(kvp.Value);
            
        }
      }
      finally
      {
        if (writer !=null)
          writer.Close();
      }
    }

    public static int WaterYear(this DateTime dt)
    {
      if (dt.Month >= 10)
        return dt.Year + 1;
      else
        return dt.Year;
    }

  }

  public enum ResampleType
  {
    Average, Max, Min, Total
  }
}
